/**
 * 不动产多源异构数据融合算法
 * 实现空间数据与非空间权属数据的智能匹配
 *
 * 主要功能：
 * 1. 空间几何匹配算法
 * 2. 属性语义匹配算法
 * 3. 多维度相似度计算
 * 4. 数据质量评估与融合
 */

class RealEstateDataFusion {
    constructor() {
        // 融合算法配置参数
        this.config = {
            spatialWeight: 0.4, // 空间匹配权重
            semanticWeight: 0.3, // 语义匹配权重
            attributeWeight: 0.3, // 属性匹配权重
            threshold: 0.75, // 融合阈值
            maxDistance: 50, // 最大空间距离(米)
        }

        // 匹配结果存储
        this.fusionResults = []
        this.matchingMatrix = []
    }

    /**
     * 主要融合算法入口
     * @param {Array} spatialData - 空间数据(3D建筑模型数据)
     * @param {Array} propertyData - 权属数据(数据库记录)
     * @returns {Array} 融合结果
     */
    fusionAlgorithm(spatialData, propertyData) {
        console.log('🚀 开始执行不动产数据融合算法...')

        // 步骤1: 数据预处理
        const processedSpatialData = this.preprocessSpatialData(spatialData)
        const processedPropertyData = this.preprocessPropertyData(propertyData)

        // 步骤2: 空间索引构建
        const spatialIndex = this.buildSpatialIndex(processedSpatialData)
        console.log('spatialIndex: ', spatialIndex)

        // 步骤3: 多维度相似度计算
        const similarityMatrix = this.calculateSimilarityMatrix(
            processedSpatialData,
            processedPropertyData,
            spatialIndex
        )

        // 步骤4: 最优匹配算法
        const matchingResults = this.optimalMatching(similarityMatrix)

        // 步骤5: 融合质量评估
        const qualityScore = this.evaluateFusionQuality(matchingResults)

        // 步骤6: 生成融合结果
        this.fusionResults = this.generateFusionResults(
            processedSpatialData,
            processedPropertyData,
            matchingResults
        )

        console.log(`✅ 数据融合完成! 匹配成功率: ${qualityScore.toFixed(2)}%`)
        return this.fusionResults
    }

    /**
     * 空间数据预处理
     * 提取建筑几何信息、位置信息、楼层信息等
     */
    preprocessSpatialData(spatialData) {
        return spatialData.map((item, index) => ({
            id: `spatial_${index}`,
            buildingId:
                item.detail?.[0]?.attribute?.build_no || `building_${index}`,
            position: {
                longitude: item.position[0],
                latitude: item.position[1],
                elevation: item.position[2] || 0,
            },
            // 计算建筑中心点
            centerPoint: this.calculateBuildingCenter(item.position),
            // 提取楼层信息
            floors:
                item.detail?.map((floor, floorIndex) => ({
                    floorId: floorIndex + 1,
                    floorHeight: 3, // 假设每层3米
                    attributes: floor.attribute,
                })) || [],
            unitNum: item.unitNum,
            // 计算建筑包围盒
            boundingBox: this.calculateBoundingBox(item.position),
            originalData: item,
        }))
    }

    /**
     * 权属数据预处理
     * 标准化权属信息，提取关键字段
     */
    preprocessPropertyData(propertyData) {
        return propertyData.map((record, index) => ({
            id: `property_${index}`,
            buildingNumber: record.building_no || record.build_no,
            unitNumber: record.unit_no || record.unit,
            floorNumber: record.floor_no || record.floor,
            roomNumber: record.room_no || record.room,
            // 标准化地址信息
            address: this.standardizeAddress(record.address),
            // 提取位置关键词
            locationKeywords: this.extractLocationKeywords(record),
            // 权属信息
            ownerInfo: {
                name: record.owner_name || record.name,
                idCard: record.id_card,
                phone: record.phone,
            },
            propertyInfo: {
                area: record.area,
                propertyType: record.property_type,
                condition: record.condition,
            },
            // 坐标信息(如果有)
            coordinates: record.coordinates
                ? {
                      longitude: record.coordinates.lng,
                      latitude: record.coordinates.lat,
                  }
                : null,
            originalData: record,
        }))
    }

    /**
     * 构建空间索引 - 提高空间查询效率
     */
    buildSpatialIndex(spatialData) {
        // 使用网格索引方法
        const gridSize = 0.001 // 约100米网格
        const spatialIndex = new Map()

        spatialData.forEach(item => {
            const gridX = Math.floor(item.position.longitude / gridSize)
            const gridY = Math.floor(item.position.latitude / gridSize)
            const gridKey = `${gridX}_${gridY}`

            if (!spatialIndex.has(gridKey)) {
                spatialIndex.set(gridKey, [])
            }
            spatialIndex.get(gridKey).push(item)
        })

        return spatialIndex
    }

    /**
     * 多维度相似度计算
     * 综合空间相似度、语义相似度、属性相似度
     */
    calculateSimilarityMatrix(spatialData, propertyData, spatialIndex) {
        const matrix = []

        spatialData.forEach((spatialItem, i) => {
            matrix[i] = []

            propertyData.forEach((propertyItem, j) => {
                // 1. 空间相似度计算
                const spatialSimilarity = this.calculateSpatialSimilarity(
                    spatialItem,
                    propertyItem
                )

                // 2. 语义相似度计算
                const semanticSimilarity = this.calculateSemanticSimilarity(
                    spatialItem,
                    propertyItem
                )

                // 3. 属性相似度计算
                const attributeSimilarity = this.calculateAttributeSimilarity(
                    spatialItem,
                    propertyItem
                )

                // 4. 综合相似度计算
                const totalSimilarity =
                    spatialSimilarity * this.config.spatialWeight +
                    semanticSimilarity * this.config.semanticWeight +
                    attributeSimilarity * this.config.attributeWeight

                matrix[i][j] = {
                    spatial: spatialSimilarity,
                    semantic: semanticSimilarity,
                    attribute: attributeSimilarity,
                    total: totalSimilarity,
                    spatialId: spatialItem.id,
                    propertyId: propertyItem.id,
                }
            })
        })

        return matrix
    }

    /**
     * 空间相似度计算
     * 基于地理位置距离、建筑编号匹配等
     */
    calculateSpatialSimilarity(spatialItem, propertyItem) {
        let similarity = 0

        // 1. 建筑编号匹配
        if (spatialItem.buildingId === propertyItem.buildingNumber) {
            similarity += 0.5
        }

        // 2. 单元号匹配
        if (spatialItem.unitNum === propertyItem.unitNumber) {
            similarity += 0.3
        }

        // 3. 地理位置距离计算
        if (propertyItem.coordinates) {
            const distance = this.calculateDistance(
                spatialItem.position,
                propertyItem.coordinates
            )

            if (distance <= this.config.maxDistance) {
                const distanceSimilarity =
                    1 - distance / this.config.maxDistance
                similarity += distanceSimilarity * 0.2
            }
        }

        return Math.min(similarity, 1.0)
    }

    /**
     * 语义相似度计算
     * 基于地址文本、关键词匹配等
     */
    calculateSemanticSimilarity(spatialItem, propertyItem) {
        let similarity = 0

        // 1. 地址关键词匹配
        const spatialKeywords = this.extractSpatialKeywords(spatialItem)
        const propertyKeywords = propertyItem.locationKeywords

        const matchedKeywords = spatialKeywords.filter(keyword =>
            propertyKeywords.includes(keyword)
        )

        if (spatialKeywords.length > 0) {
            similarity +=
                (matchedKeywords.length / spatialKeywords.length) * 0.6
        }

        // 2. 楼层信息匹配
        const floorMatch = spatialItem.floors.some(
            floor => floor.floorId === propertyItem.floorNumber
        )

        if (floorMatch) {
            similarity += 0.4
        }

        return Math.min(similarity, 1.0)
    }

    /**
     * 属性相似度计算
     * 基于面积、房型、用途等属性匹配
     */
    calculateAttributeSimilarity(spatialItem, propertyItem) {
        let similarity = 0

        // 获取空间数据中的属性信息
        const spatialAttrs = spatialItem.floors[0]?.attributes || {}
        const propertyAttrs = propertyItem.propertyInfo

        // 1. 面积匹配（允许10%误差）
        if (spatialAttrs.area && propertyAttrs.area) {
            const areaDiff = Math.abs(spatialAttrs.area - propertyAttrs.area)
            const areaRatio =
                areaDiff / Math.max(spatialAttrs.area, propertyAttrs.area)

            if (areaRatio <= 0.1) {
                similarity += 0.4
            }
        }

        // 2. 房屋状态匹配
        if (spatialAttrs.condition === propertyAttrs.condition) {
            similarity += 0.3
        }

        // 3. 房屋类型匹配
        if (spatialAttrs.property_type === propertyAttrs.propertyType) {
            similarity += 0.3
        }

        return Math.min(similarity, 1.0)
    }

    /**
     * 最优匹配算法
     * 使用匈牙利算法或贪心算法找到最佳匹配方案
     */
    optimalMatching(similarityMatrix) {
        const matches = []
        const usedSpatial = new Set()
        const usedProperty = new Set()

        // 贪心算法：按相似度从高到低匹配
        const allPairs = []

        for (let i = 0; i < similarityMatrix.length; i++) {
            for (let j = 0; j < similarityMatrix[i].length; j++) {
                if (similarityMatrix[i][j].total >= this.config.threshold) {
                    allPairs.push({
                        spatialIndex: i,
                        propertyIndex: j,
                        similarity: similarityMatrix[i][j].total,
                        details: similarityMatrix[i][j],
                    })
                }
            }
        }

        // 按相似度排序
        allPairs.sort((a, b) => b.similarity - a.similarity)

        // 贪心匹配
        for (const pair of allPairs) {
            if (
                !usedSpatial.has(pair.spatialIndex) &&
                !usedProperty.has(pair.propertyIndex)
            ) {
                matches.push(pair)
                usedSpatial.add(pair.spatialIndex)
                usedProperty.add(pair.propertyIndex)
            }
        }

        return matches
    }

    /**
     * 融合质量评估
     */
    evaluateFusionQuality(matchingResults) {
        if (matchingResults.length === 0) return 0

        const avgSimilarity =
            matchingResults.reduce((sum, match) => sum + match.similarity, 0) /
            matchingResults.length

        return avgSimilarity * 100
    }

    /**
     * 生成最终融合结果
     */
    generateFusionResults(spatialData, propertyData, matchingResults) {
        return matchingResults.map(match => ({
            matchId: `match_${match.spatialIndex}_${match.propertyIndex}`,
            confidence: match.similarity,
            spatialData: spatialData[match.spatialIndex],
            propertyData: propertyData[match.propertyIndex],
            fusionQuality: {
                spatialSimilarity: match.details.spatial,
                semanticSimilarity: match.details.semantic,
                attributeSimilarity: match.details.attribute,
                overallSimilarity: match.details.total,
            },
            // 融合后的统一数据结构
            fusedData: this.createUnifiedDataStructure(
                spatialData[match.spatialIndex],
                propertyData[match.propertyIndex]
            ),
        }))
    }

    /**
     * 创建统一的数据结构
     */
    createUnifiedDataStructure(spatialData, propertyData) {
        return {
            id: `unified_${spatialData.buildingId}_${spatialData.unitNum}`,
            building: {
                buildingId: spatialData.buildingId,
                position: spatialData.position,
                geometry: spatialData.boundingBox,
            },
            unit: {
                unitNumber: spatialData.unitNum,
                floors: spatialData.floors,
            },
            property: {
                owner: propertyData.ownerInfo,
                propertyInfo: propertyData.propertyInfo,
                address: propertyData.address,
            },
            spatial: spatialData.originalData,
            attributes: propertyData.originalData,
        }
    }

    // === 辅助函数 ===

    calculateBuildingCenter(position) {
        return {
            longitude: position[0],
            latitude: position[1],
            elevation: position[2] || 0,
        }
    }

    calculateBoundingBox(position) {
        const offset = 0.0001 // 约10米
        return {
            minLon: position[0] - offset,
            maxLon: position[0] + offset,
            minLat: position[1] - offset,
            maxLat: position[1] + offset,
        }
    }

    standardizeAddress(address) {
        if (!address) return ''
        return address.replace(/[　\s]+/g, ' ').trim()
    }

    extractLocationKeywords(record) {
        const keywords = []
        if (record.address) {
            // 提取地址中的关键词
            const addressKeywords =
                record.address.match(/[\u4e00-\u9fa5]+/g) || []
            keywords.push(...addressKeywords)
        }
        return keywords
    }

    extractSpatialKeywords(spatialItem) {
        const keywords = []
        if (spatialItem.buildingId) {
            keywords.push(spatialItem.buildingId)
        }
        return keywords
    }

    calculateDistance(pos1, pos2) {
        const R = 6371000 // 地球半径(米)
        const lat1Rad = (pos1.latitude * Math.PI) / 180
        const lat2Rad = (pos2.latitude * Math.PI) / 180
        const deltaLatRad = ((pos2.latitude - pos1.latitude) * Math.PI) / 180
        const deltaLonRad = ((pos2.longitude - pos1.longitude) * Math.PI) / 180

        const a =
            Math.sin(deltaLatRad / 2) * Math.sin(deltaLatRad / 2) +
            Math.cos(lat1Rad) *
                Math.cos(lat2Rad) *
                Math.sin(deltaLonRad / 2) *
                Math.sin(deltaLonRad / 2)
        const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))

        return R * c
    }

    /**
     * 获取融合统计信息
     */
    getFusionStatistics() {
        if (this.fusionResults.length === 0) {
            return { message: '暂无融合结果' }
        }

        const stats = {
            totalMatches: this.fusionResults.length,
            averageConfidence:
                this.fusionResults.reduce(
                    (sum, result) => sum + result.confidence,
                    0
                ) / this.fusionResults.length,
            qualityDistribution: {
                high: this.fusionResults.filter(r => r.confidence >= 0.8)
                    .length,
                medium: this.fusionResults.filter(
                    r => r.confidence >= 0.6 && r.confidence < 0.8
                ).length,
                low: this.fusionResults.filter(r => r.confidence < 0.6).length,
            },
        }

        return stats
    }

    /**
     * 导出融合结果
     */
    exportResults(format = 'json') {
        const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
        const filename = `fusion_results_${timestamp}`

        if (format === 'json') {
            const jsonData = JSON.stringify(this.fusionResults, null, 2)
            return { filename: `${filename}.json`, data: jsonData }
        }

        // 可以扩展其他格式...
        return { filename, data: this.fusionResults }
    }
}
